classdef CRExportImportService < handle
    % CRExportImportService - CR表单数据导出导入服务
    % 遵循DO-178第4条规则：业务逻辑与GUI分离
    % 
    % 功能：
    % - 导出CR表单数据到JSON格式
    % - 导出CR表单数据到Markdown格式  
    % - 从JSON文件导入CR表单数据
    %
    % 作者：系统
    % 日期：2025-01-20
    % 版本：2.0 (支持CR API v2.0)
    
    methods (Static)
        
        function success = exportToJSON(crData, filePath)
            % 导出CR数据到JSON文件
            % 输入：
            %   crData - CR表单数据结构
            %   filePath - 输出文件路径
            % 输出：
            %   success - 导出是否成功
            
            try
                % 数据验证
                if isempty(crData)
                    error('CR数据不能为空');
                end
                
                if isempty(filePath)
                    error('文件路径不能为空');
                end
                
                % 确保输出目录存在
                [outputDir, ~, ~] = fileparts(filePath);
                if ~isempty(outputDir) && ~exist(outputDir, 'dir')
                    mkdir(outputDir);
                end
                
                % 转换数据格式以支持JSON序列化
                jsonData = CRExportImportService.prepareDataForJSON(crData);
                
                % 写入JSON文件
                jsonStr = jsonencode(jsonData, 'PrettyPrint', true);
                fid = fopen(filePath, 'w', 'n', 'UTF-8');
                if fid == -1
                    error('无法创建文件：%s', filePath);
                end
                
                fprintf(fid, '%s', jsonStr);
                fclose(fid);
                
                success = true;
                
            catch ME
                success = false;
                error('导出JSON失败：%s', ME.message);
            end
        end
        
        function success = exportToMarkdown(crData, filePath)
            % 导出CR数据到Markdown文件
            % 输入：
            %   crData - CR表单数据结构
            %   filePath - 输出文件路径
            % 输出：
            %   success - 导出是否成功
            
            try
                % 数据验证
                if isempty(crData)
                    error('CR数据不能为空');
                end
                
                if isempty(filePath)
                    error('文件路径不能为空');
                end
                
                % 确保输出目录存在
                [outputDir, ~, ~] = fileparts(filePath);
                if ~isempty(outputDir) && ~exist(outputDir, 'dir')
                    mkdir(outputDir);
                end
                
                % 生成Markdown内容
                mdContent = CRExportImportService.generateMarkdownContent(crData);
                
                % 写入Markdown文件
                fid = fopen(filePath, 'w', 'n', 'UTF-8');
                if fid == -1
                    error('无法创建文件：%s', filePath);
                end
                
                fprintf(fid, '%s', mdContent);
                fclose(fid);
                
                success = true;
                
            catch ME
                success = false;
                error('导出Markdown失败：%s', ME.message);
            end
        end
        
        function [success, crData] = importFromJSON(filePath)
            % 从JSON文件导入CR数据
            % 输入：
            %   filePath - JSON文件路径
            % 输出：
            %   success - 导入是否成功
            %   crData - 导入的CR数据结构
            
            try
                % 文件验证
                if isempty(filePath)
                    error('文件路径不能为空');
                end
                
                if ~exist(filePath, 'file')
                    error('文件不存在：%s', filePath);
                end
                
                % 读取JSON文件
                fid = fopen(filePath, 'r', 'n', 'UTF-8');
                if fid == -1
                    error('无法打开文件：%s', filePath);
                end
                
                jsonStr = fread(fid, '*char')';
                fclose(fid);
                
                % 解析JSON
                jsonData = jsondecode(jsonStr);
                
                % 转换回CR数据格式
                crData = CRExportImportService.convertFromJSON(jsonData);
                
                success = true;
                
            catch ME
                success = false;
                crData = [];
                error('导入JSON失败：%s', ME.message);
            end
        end
        
    end
    
    methods (Static, Access = private)
        
        function jsonData = prepareDataForJSON(crData)
            % 准备数据以支持JSON序列化
            % 支持CR API v2.0的14个字段（10必填+4可选）
            jsonData = struct();
            
            % ========== 必填字段（10个）==========
            % 基础信息（5个）
            if isfield(crData, 'project')
                jsonData.project = crData.project;
            end
            if isfield(crData, 'ticketNumber')
                jsonData.ticketNumber = crData.ticketNumber;
            end
            if isfield(crData, 'reporter')
                jsonData.reporter = crData.reporter;
            end
            if isfield(crData, 'changeCategory')
                jsonData.changeCategory = crData.changeCategory;
            end
            if isfield(crData, 'urgency')
                jsonData.urgency = crData.urgency;
            end
            
            % 变更描述和分析（3个）
            if isfield(crData, 'changeDescription')
                jsonData.changeDescription = CRExportImportService.cellArrayToString(crData.changeDescription);
            end
            if isfield(crData, 'relatedRequirements')
                jsonData.relatedRequirements = crData.relatedRequirements;
            end
            if isfield(crData, 'impactAnalysis')
                jsonData.impactAnalysis = CRExportImportService.cellArrayToString(crData.impactAnalysis);
            end
            
            % 分配和审批（2个）
            if isfield(crData, 'assignee')
                jsonData.assignee = crData.assignee;
            end
            if isfield(crData, 'approver')
                jsonData.approver = crData.approver;
            end
            
            % ========== 可选字段（4个）==========
            if isfield(crData, 'changeSource')
                jsonData.changeSource = crData.changeSource;
            end
            if isfield(crData, 'verificationStatus')
                jsonData.verificationStatus = CRExportImportService.cellArrayToString(crData.verificationStatus);
            end
            if isfield(crData, 'implementationPlan')
                jsonData.implementationPlan = CRExportImportService.cellArrayToString(crData.implementationPlan);
            end
            if isfield(crData, 'changeApproach')
                jsonData.changeApproach = CRExportImportService.cellArrayToString(crData.changeApproach);
            end
            
            % 添加导出时间戳
            jsonData.exportTime = char(datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss'));
            jsonData.exportVersion = '2.0';
        end
        
        function mdContent = generateMarkdownContent(crData)
            % 生成Markdown内容 - 支持CR API v2.0
            mdContent = sprintf('# CR表单数据 (API v2.0)\n\n');
            mdContent = [mdContent sprintf('**生成时间：** %s\n\n', datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss'))];
            
            % 基础信息表格
            mdContent = [mdContent sprintf('## 基础信息\n\n')];
            mdContent = [mdContent sprintf('| 字段 | 值 |\n')];
            mdContent = [mdContent sprintf('|------|-----|\n')];
            if isfield(crData, 'project')
                mdContent = [mdContent sprintf('| 项目名称 | %s |\n', crData.project)];
            end
            if isfield(crData, 'ticketNumber')
                mdContent = [mdContent sprintf('| 票号 | %s |\n', crData.ticketNumber)];
            end
            if isfield(crData, 'reporter')
                mdContent = [mdContent sprintf('| 提报人 | %s |\n', crData.reporter)];
            end
            if isfield(crData, 'changeCategory')
                mdContent = [mdContent sprintf('| 变更类别 | %s |\n', crData.changeCategory)];
            end
            if isfield(crData, 'urgency')
                mdContent = [mdContent sprintf('| 紧急度 | %s |\n', crData.urgency)];
            end
            if isfield(crData, 'assignee')
                mdContent = [mdContent sprintf('| 分配人员 | %s |\n', crData.assignee)];
            end
            if isfield(crData, 'approver')
                mdContent = [mdContent sprintf('| 审批人 | %s |\n', crData.approver)];
            end
            if isfield(crData, 'changeSource')
                mdContent = [mdContent sprintf('| 变更来源 | %s |\n', crData.changeSource)];
            end
            mdContent = [mdContent sprintf('\n')];
            
            % 变更描述
            if isfield(crData, 'changeDescription')
                mdContent = [mdContent sprintf('## 变更描述\n\n')];
                changeDesc = CRExportImportService.cellArrayToString(crData.changeDescription);
                mdContent = [mdContent sprintf('%s\n\n', changeDesc)];
            end
            
            % 关联需求
            if isfield(crData, 'relatedRequirements')
                mdContent = [mdContent sprintf('## 关联需求\n\n')];
                mdContent = [mdContent sprintf('%s\n\n', crData.relatedRequirements)];
            end
            
            % 影响性分析
            if isfield(crData, 'impactAnalysis')
                mdContent = [mdContent sprintf('## 影响性分析\n\n')];
                impact = CRExportImportService.cellArrayToString(crData.impactAnalysis);
                mdContent = [mdContent sprintf('%s\n\n', impact)];
            end
            
            % 验证状态
            if isfield(crData, 'verificationStatus')
                mdContent = [mdContent sprintf('## 验证状态\n\n')];
                verification = CRExportImportService.cellArrayToString(crData.verificationStatus);
                mdContent = [mdContent sprintf('%s\n\n', verification)];
            end
            
            % 实施计划
            if isfield(crData, 'implementationPlan')
                mdContent = [mdContent sprintf('## 实施计划\n\n')];
                implementation = CRExportImportService.cellArrayToString(crData.implementationPlan);
                mdContent = [mdContent sprintf('%s\n\n', implementation)];
            end
            
            % 变更措施
            if isfield(crData, 'changeApproach')
                mdContent = [mdContent sprintf('## 变更措施\n\n')];
                approach = CRExportImportService.cellArrayToString(crData.changeApproach);
                mdContent = [mdContent sprintf('%s\n\n', approach)];
            end
        end
        
        function crData = convertFromJSON(jsonData)
            % 从JSON数据转换回CR数据格式 - 支持CR API v2.0
            crData = struct();
            
            % ========== 必填字段（10个）==========
            % 基础信息（5个）
            if isfield(jsonData, 'project')
                crData.project = jsonData.project;
            end
            if isfield(jsonData, 'ticketNumber')
                crData.ticketNumber = jsonData.ticketNumber;
            end
            if isfield(jsonData, 'reporter')
                crData.reporter = jsonData.reporter;
            end
            if isfield(jsonData, 'changeCategory')
                crData.changeCategory = jsonData.changeCategory;
            end
            if isfield(jsonData, 'urgency')
                crData.urgency = jsonData.urgency;
            end
            
            % 变更描述和分析（3个）
            if isfield(jsonData, 'changeDescription')
                crData.changeDescription = CRExportImportService.stringToCellArray(jsonData.changeDescription);
            end
            if isfield(jsonData, 'relatedRequirements')
                crData.relatedRequirements = jsonData.relatedRequirements;
            end
            if isfield(jsonData, 'impactAnalysis')
                crData.impactAnalysis = CRExportImportService.stringToCellArray(jsonData.impactAnalysis);
            end
            
            % 分配和审批（2个）
            if isfield(jsonData, 'assignee')
                crData.assignee = jsonData.assignee;
            end
            if isfield(jsonData, 'approver')
                crData.approver = jsonData.approver;
            end
            
            % ========== 可选字段（4个）==========
            if isfield(jsonData, 'changeSource')
                crData.changeSource = jsonData.changeSource;
            end
            if isfield(jsonData, 'verificationStatus')
                crData.verificationStatus = CRExportImportService.stringToCellArray(jsonData.verificationStatus);
            end
            if isfield(jsonData, 'implementationPlan')
                crData.implementationPlan = CRExportImportService.stringToCellArray(jsonData.implementationPlan);
            end
            if isfield(jsonData, 'changeApproach')
                crData.changeApproach = CRExportImportService.stringToCellArray(jsonData.changeApproach);
            end
        end
        
        function str = cellArrayToString(cellArray)
            % 将cell数组转换为字符串
            if iscell(cellArray)
                str = strjoin(cellArray, '\n');
            else
                str = string(cellArray);
            end
        end
        
        function cellArray = stringToCellArray(str)
            % 将字符串转换为cell数组
            if ischar(str) || isstring(str)
                cellArray = strsplit(str, '\n');
            else
                cellArray = {str};
            end
        end
        
    end
end

